home *** CD-ROM | disk | FTP | other *** search
- ;WATCH.ASM
- ;resident routine watches programs going resident
- ;and keeps a list of changes in interrupt vectors to an internal data structure
- ; written to use MicroSoft MASM version 4
- ; written by Kim Kokkonen, TurboPower Software
- ;
- ; VERSION 2.2 3/4/87
- ; First release, version to be consistent with MAPMEM.PAS
- ; VERSION 2.3 5/1/87
- ; Sets up a separate stack for the interrupt handlers
- ; to solve problem first noticed with EMMCACHE and WATCH
- ; Changes approach - store all vector information in RAM buffers
- ; No disk access at all by WATCH
- ; Better check for multiple installation
- ; Changed to use MASM
- ; VERSION 2.4 5/17/87
- ; for consistency with RELEASE
- ; VERSION 2.5 5/28/87
- ; save flags in int21 handler
- ;
-
- Cseg segment public para
- assume cs:Cseg, ds:nothing, es:nothing, ss:nothing
-
- org 080H
- cmdline label byte ;pointer to command line
-
- org 100H
- comentry: jmp init
-
- ;******************************************************************************
- ;resident data section follows
- ;******************************************************************************
-
- ;put the following in the MAP file
- public bmesg,origv,prevv,vpos,vchg
-
- ;resident data structures not part of COM file
- vchg equ 220H ;location of data area (>= offset bmesg)
- vrecsize equ 8 ;number of bytes per vector change record
- vsize equ 80H*vrecsize ;size of vector change area in bytes
- ;space for 128 changes of vector here
-
- ;vector table buffers
- origv equ vchg+vsize ;location of original vector table
- veclen equ 400H ;size of vector table in bytes
- prevv equ origv+veclen ;location of current vector table
- newstackpos equ prevv+veclen ;location of newstack
- ssize equ 0080H ;number of bytes in temporary stack
- newloc equ newstackpos+ssize ;location for relocated installation code
-
- even
- vpos dw 0 ;next position to write in data area
-
- ;temporary stack used by interrupt handler
- newss dw 0 ;segment of our temporary stack
- newsp dw 0 ;initial stack pointer
-
- ;information saved about the calling program
- oldss dw ? ;stack segment
- oldsp dw ? ;stack pointer
- curpsp dw ? ;program segment
-
- ;id code for a PSP data block
- pspid equ 0FFFFH ;id used to indicate a PSP block
- ;int16H function call for id check
- getid equ 'wa' ;function code for int16
- chkid equ 'WA' ;returned by int16 getid check
-
- ;previous interrupt handlers
- kbd_int label dword
- old16 dw 2 dup (?) ;old int16 vector
- dos_int label dword
- old21 dw 2 dup (?) ;old int21 vector
- tsr_int label dword
- old27 dw 2 dup (?) ;old int27 vector
-
- ;***********************************************************************
- ;interrupt handler for int16
- ;used only to avoid reinstallation
- newint16 proc near
- assume ds:nothing
- pushf ;save application flags
- sti
- cmp ax,getid ;see if our id function
- jne ex16 ;no, pass on to previous int16
-
- mov ax,chkid ;return id code
- popf
- iret ;back to caller
-
- ex16: popf
- jmp kbd_int ;transfer control to the previous int16
- newint16 endp
-
- ;***********************************************************************
- ;interrupt handler for int21
- newint21 proc near
- assume ds:nothing
- pushf ;save flags
- cmp ah,31H
- jne ex21
- call checkvec ;call routine to check vector table
- ex21: popf
- jmp dos_int ;transfer control to the previous int21 vector
- newint21 endp
-
- ;***********************************************************************
- ;interrupt handler for int27
- newint27 proc near
- assume ds:nothing
- call checkvec
- ex27: jmp tsr_int ;transfer control to the previous int27 vector
- newint27 endp
-
- ;***********************************************************************
- ;procedure checkvec
- ; compares vectors to previous installation
- ; stores a new vector buffer
- ; writes information to wfile
-
- checkvec proc near
- assume ds:nothing
-
- ;save current stack
- mov oldss,ss
- mov oldsp,sp
-
- ;switch to our stack
- cli
- mov ss,newss
- mov sp,newsp
- sti
-
- ;store registers
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- ;get DS set up as CS
- mov ax,cs
- mov ds,ax
- assume ds:cseg
-
- mov ah,51H ;get current PSP
- pushf
- call dos_int ;bx returns PSP
-
- call vechdr ;store the PSP segment of the program going resident
- call cmpvec ;scan the vector table looking for changes from our buffer
- mov di,prevv ;save the new version of the vector table
- call savevec
-
- ;restore registers
- pop es
- pop ds
- assume ds:nothing
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
-
- ;restore stack
- cli
- mov ss,oldss
- mov sp,oldsp
- sti
-
- ret
- checkvec endp
-
- ;**************************************************************************
- ;procedure vechdr
- ; writes a header to the vector data area for this new TSR
- ; on entry:
- ; bx has PSP of the new TSR
- ;
- vechdr proc near
- assume ds:cseg
- cmp vpos,vsize-vrecsize ;assure room for next record
- ja vecex ;ignore if no room
-
- push di
- mov di,vpos ;index into vchg array
- mov word ptr [di+vchg],pspid ;store id word
- mov word ptr [di+vchg+2],bx ;store PSP value
- ;two words in record left unitialized
- add vpos,vrecsize ;move to next data element
- pop di
-
- vecex: ret
- vechdr endp
-
- ;**************************************************************************
- ;procedure wrchg
- ; writes information about changed vectors to the data area
- ; on entry
- ; ax has changed vector number
- ; ds points to segment 0
- ; on exit:
- ; flags changed
- ;
- wrchg proc near
- assume ds:nothing, es:nothing
- cmp vpos,vsize-vrecsize ;assure room for next record
- ja wrcex
-
- push ax
- push si
- push di
-
- mov di,vpos ;index into vchg array
- mov cs:[di+vchg],ax ;store interrupt vector number
-
- mov si,ax
- shl si,1
- shl si,1 ;get address of vector
- mov ax,[si] ;get offset of vector
- mov cs:[di+vchg+2],ax ;store vector offset
- mov ax,[si+2] ;get segment
- mov cs:[di+vchg+4],ax ;store segment
- ;one word in record left unused
- add vpos,vrecsize ;move to next data element
-
- pop di
- pop si
- pop ax
-
- wrcex: ret
- wrchg endp
-
- ;**************************************************************************
- ;procedure cmpvec
- ; compares vectors in buffer to those in use
- ; writes numbers of those different to data area
- ; on exit:
- ; ax,si,di destroyed
- ; flags changed
- ;
- cmpvec proc near
- assume ds:nothing, es:nothing
- push ds
- push es
-
- xor si,si ;source offset 0
- mov ds,si ;source address segment 0
- mov ax,cs
- mov es,ax
- xor ax,ax ;vector counter
- mov di,prevv ;destination offset
- cld ;upward direction
-
- nexvec: cmpsw ;compare offsets
- je cmpseg ;compare segments if offsets equal
- call wrchg ;write changed vector
- cmpsw ;compare next word, ignore result
- jmp short vecinc
-
- cmpseg: cmpsw ;compare segments
- je vecinc
- call wrchg ;write changed vector
-
- vecinc: inc ax ;next vector number
- cmp ax,00FFH
- jbe nexvec ;continue until 256 vectors checked
-
- pop es
- pop ds
- ret
- cmpvec endp
-
- ;**************************************************************************
- ;procedure savevec
- ; saves image of interrupt vectors
- ; on entry:
- ; di has destination offset
- ; on exit:
- ; ax,cx,si,di destroyed
- ; flags changed
- ;
- savevec proc near
- assume ds:nothing, es:nothing
- push ds
- push es
- xor si,si ;offset 0
- mov ds,si ;source address segment 0
- mov ax,cs
- mov es,ax ;destination always in this code segment
- mov cx,200H ;512 integers to store
- cld ;copy up
- rep movsw ;copy vectors to our table
- pop es
- pop ds
- ret
- savevec endp ;of proc savevec
-
-
- ;**************************************************************************
- ;resident portion above, temporary portion below
- ;**************************************************************************
-
- ;temporary strings
- even
- bmesg db 13,10,'Cannot install WATCH more than once....',13,10,36
- mesg db 13,10,'WATCH 2.5 successfully installed',13,10,36
- pname db 'TSR WATCHER'
- plen equ $-pname ;length of string
-
- ;**************************************************************************
- ;install new handlers for DOS go-resident services
- init proc near
- assume ds:cseg
-
- ;use int 16h test to check for previous installation
- mov ax,getid ;int16h diagnostic request
- int 16h ;now, ax=chkid if installed
- cmp ax,chkid ;TSR already installed?
- jne success ;no - jump if not installed
-
- ;error exit
- mov dx,offset bmesg ;error message
- mov ah,09H
- int 21H ;DOS print string
- mov ax,4C01H ;exit with error
- int 21H
-
- ;print a success message
- success: mov dx,offset mesg ;start of message to write
- mov ah,09H
- int 21H ;DOS print string
-
- ;relocate ourselves out of the way of the vector tables
- mov ax,cs
- mov es,ax
- mov di,newloc+10H
- push di ;will act as a return address
- mov si,offset newstk
- mov cx,lastcode-newstk
- rep movsb ;move code
- ret ;"return" to the relocated code
-
- ;initialize location of WATCH stack
- newstk: mov newsp,newstackpos+ssize
- mov newss,cs ;stack seg is code seg
-
- ;get int 16H vector
- mov ax,3516H ;GetVector DOS function call
- int 21H
- mov old16,bx ;store first word of old21
- mov old16[2],es ;store second word
-
- ;get int 21H vector
- mov ax,3521H ;GetVector DOS function call
- int 21H
- mov old21,bx ;store first word of old21
- mov old21[2],es ;store second word
-
- ;get int 27H vector
- mov ax,3527H ;GetVector DOS function call
- int 21H
- mov old27,bx ;store first word of old27 (offset)
- mov old27[2],es ;store second word (segment)
-
- ;put an id label at offset 80H to allow other programs to recognize WATCH
- mov ax,cs
- mov es,ax
- mov cx,plen ;length of name string
- mov si,offset pname ;offset of name string
- mov di,offset cmdline ;offset of DOS command line
- cld ;transfer in forward direction
- mov al,cl
- stosb ;store length byte first
- rep movsb ;transfer characters
-
- ;store image of original vector table (overwrites messages)
- mov di,origv
- mov ax,offset savevec
- call ax ;absolute call works as code is moved
-
- ;store it again into the current vector table
- mov di,prevv
- mov ax,offset savevec
- call ax ;absolute call works as code is moved
-
- ;install the new vectors
- mov ax,2516H
- mov dx,offset newint16
- int 21H
- mov ax,2521H
- mov dx,offset newint21
- int 21H
- mov ax,2527H
- mov dx,offset newint27
- int 21H
-
- ;terminate and stay resident
- mov dx,(newloc+15) shr 4
- mov ax,3100H ;return success code
- int 21H
-
- lastcode:
- init endp
-
- Cseg ends
- end ComEntry